package org.ykh.oos.controller;

import com.aliyun.oss.OSS;
import com.aliyuncs.exceptions.ClientException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.ykh.oos.service.OssService;
import org.ykh.service.exception.BusinessException;
import org.ykh.service.result.Result;

import org.ykh.oos.pojo.dto.OssCallbackDto;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Map;

/**
 * @author ykh
 * @create 2023-02-21 1:06
 */
@RestController
@Slf4j
@CrossOrigin
@RequestMapping("/api")
public class OssController{

    private OssService ossService;

    public OssController(OssService ossService) {
        this.ossService = ossService;
    }

    /**
     * 上传到本地
     * @param multipartFile
     * @return
     * @throws IOException
     */
    @PostMapping("/upload")
    public Result<?> upload(@RequestParam("file") MultipartFile multipartFile) throws IOException {
//            multipartFile.transferTo(new File("C:\\Users\\YKH\\Desktop\\" + multipartFile.getOriginalFilename()));
        try {
            ossService.upload("test", multipartFile.getName(), multipartFile.getInputStream());
        } catch (ClientException e) {
            log.error("上传失败", e);
            throw new BusinessException("30010", "上传失败" );
        }

        return Result.ok();
    }

    /**
     * 获取上传签名，签名后直传
     * @return
     */
    @GetMapping("/policy")
    public Result<Map<String, String>> policy() {
        OSS ossClient = null;
        try {
            ossClient = ossService.createOssClientV1();
            if (ossClient == null) {
                throw new BusinessException("ossClient获取失败", "30001");
            }
            return Result.ok(ossService.policyCallback(ossClient, "test/"));
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }


    /**
     * 处理OSS回调请求的API接口。
     * 此接口用于处理来自OSS（对象存储服务）的回调请求，进行请求验证和相应的业务处理。
     *
     * @param request        HttpServletRequest对象，代表客户端的HTTP请求。
     * @param response       HttpServletResponse对象，用于向客户端发送响应。
     * @param contentLength  请求内容的长度，通过请求头中的"content-length"获取。
     * @param authorization  请求中的授权信息，通过请求头中的"Authorization"获取。
     * @param pubKeyInput    公钥URL，通过请求头中的"x-oss-pub-key-url"获取，用于验证回调内容。
     * @param ossCallbackDto 包含回调请求的具体数据，通过请求参数获取。
     * @return ResponseEntity对象，表示API的响应，包括响应状态码和响应体。
     * @throws IOException        当处理请求或响应时发生IO错误。
     * @throws URISyntaxException 当解析URI语法时发生错误。
     */
    public Result<?> respond(HttpServletRequest request, HttpServletResponse response, Integer contentLength,
                             String authorization, String pubKeyInput, OssCallbackDto ossCallbackDto
    ) throws IOException,
            URISyntaxException {
        //验证响应
        //TODO:目前这个验证还有一些问题
        if (!ossService.VerifyOSSCallbackRequest(request, contentLength, authorization, pubKeyInput)) {
            log.warn("oss回调来源校验失败");
            throw new BusinessException("4100", "请求被拒绝", HttpStatus.UNAUTHORIZED);
        }
        //业务代码
        //...
        return Result.ok();
    }

    @PostMapping(value = "/callback", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
    public Result<?> respond_form(HttpServletRequest request, HttpServletResponse response,
                                  @RequestHeader("content-length") Integer contentLength,
                                  @RequestHeader("Authorization") String authorization,
                                  @RequestHeader("x-oss-pub-key-url") String pubKeyInput,
                                  OssCallbackDto ossCallbackDto
    ) throws IOException,
            URISyntaxException {
        return respond(request, response, contentLength, authorization, pubKeyInput, ossCallbackDto);
    }

    @PostMapping(value = "/callback", consumes = {MediaType.APPLICATION_JSON_VALUE})
    public Result<?> respond_json(HttpServletRequest request, HttpServletResponse response,
                                  @RequestHeader("content-length") Integer contentLength,
                                  @RequestHeader("Authorization") String authorization,
                                  @RequestHeader("x-oss-pub-key-url") String pubKeyInput,
                                  @RequestBody OssCallbackDto ossCallbackDto
    ) throws IOException,
            URISyntaxException {
        return respond(request, response, contentLength, authorization, pubKeyInput, ossCallbackDto);
    }
}